//
//    Build a Density 3D texture
//


-- VS


layout(location=0) in vec4 inPositionUV;

out block {
  vec4 positionCS;
  vec3 coordWS;
  int instanceID;
} Out;

uniform vec3  uChunkPositionWS;
uniform float uChunkSize;
uniform float uInvChunkDim;

void main()
{
# define Position  inPositionUV.xy
# define TexCoord  inPositionUV.zw

  Out.positionCS = vec4( Position, 0.0f, 1.0f);

  // in [0..1]
  vec3 cellCoord = vec3( TexCoord, gl_InstanceID * uInvChunkDim);


#if 1
  float VoxelDim = 33;          // # of cell corners
  float VoxelDimMinusOne = VoxelDim-1.0f;  // # of cells
  vec2 wsVoxelSize = vec2(1.0/(VoxelDim-2.0f), 0);  // could be 1/63, 1/31, 1/15 depending on LOD
  vec2 InvVoxelDim = vec2(1.0/VoxelDim, 0); 
  vec2 InvVoxelDimMinusOne = vec2(1.0/VoxelDimMinusOne, 0); 
  float Margin                      = 0;
  float VoxelDimPlusMargins         = VoxelDim+2*Margin;
  float VoxelDimPlusMarginsMinusOne = VoxelDimPlusMargins-1.0f;
  vec2 InvVoxelDimPlusMargins         = vec2(1.0/VoxelDimPlusMargins, 0);
  vec2 InvVoxelDimPlusMarginsMinusOne = vec2(1.0/VoxelDimPlusMarginsMinusOne, 0);
  
  
    // chunkCoord is in [0..1] range
    vec3 chunkCoord = vec3( TexCoord, gl_InstanceID * InvVoxelDimPlusMargins.x);
    
      // HACK #1 - because in DX, when you render a quad with uv's in [0..1],
      //           the upper left corner will be a 0 and the lower right
      //           corner will be at 1 (it should be at 63/64, or whatever).
      chunkCoord.xyz *= VoxelDim.x*InvVoxelDimMinusOne.x;  
      
    // extChunkCoord goes outside that range, so we also compute
    // some voxels outside of the chunk
    vec3 extChunkCoord = (chunkCoord*VoxelDimPlusMargins.x - Margin)*InvVoxelDim.x;
                                
    Out.coordWS = uChunkPositionWS + uChunkSize*extChunkCoord; 

#else
  Out.coordWS = uChunkPositionWS + uChunkSize * cellCoord;
#endif

  Out.instanceID = gl_InstanceID;
}

--

//------------------------------------------------------------------------------

-- GS

// The Geometry Shader sole purpose is to set the destination layer

layout(triangles) in;
layout(triangle_strip, max_vertices=3) out;

in block {
  vec4 positionCS;
  vec3 coordWS;
  int instanceID;
} In[];

out block {
  vec3 coordWS;
  flat int instanceID;
} Out;

void main()
{
  // Per Primitives attribute
  gl_Layer       = In[0].instanceID;
  Out.instanceID = In[0].instanceID;
  
  // Per vertices attribute
  gl_Position = In[0].positionCS;
  Out.coordWS = In[0].coordWS;
  EmitVertex();
  
  gl_Position = In[1].positionCS;
  Out.coordWS = In[1].coordWS;
  EmitVertex();
  
  gl_Position = In[2].positionCS;
  Out.coordWS = In[2].coordWS;
  EmitVertex();  
  
  EndPrimitive();
}


--

//------------------------------------------------------------------------------

-- FS

in block {
  vec3 coordWS;
  flat int instanceID;
} In;

out float fragDensity;

uniform float uInvChunkDim;


float compute_density(in vec3 posWS)
{
  float rad = 2.2f;
  return rad - length(posWS);
}

void main()
{
  vec3 coords = In.coordWS;
  fragDensity = compute_density( coords );
}

